Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code attributes for Logback #6591

Merged
merged 14 commits into from
Sep 13, 2022

Conversation

jeanbisutti
Copy link
Member

Add code attributes for Logback:

  • SemanticAttributes.CODE_FILEPATH
  • SemanticAttributes.CODE_NAMESPACE
  • SemanticAttributes.CODE_FUNCTION
  • SemanticAttributes.CODE_LINENO

@jeanbisutti jeanbisutti requested a review from a team September 12, 2022 15:29
@jeanbisutti jeanbisutti marked this pull request as draft September 12, 2022 15:29
@@ -25,6 +25,7 @@ public class OpenTelemetryAppender extends UnsynchronizedAppenderBase<ILoggingEv
new LogEmitterProviderHolder();

private volatile boolean captureExperimentalAttributes = false;
private volatile boolean captureCodeAttributes = false;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted first that the captureCodeAttributes property would be an AtomicBoolean, but I have noticed after that captureExperimentalAttributes is a boolean, so I keep the same way of doing

@jeanbisutti jeanbisutti marked this pull request as ready for review September 12, 2022 15:42
Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice 👍

@@ -62,6 +65,17 @@ public void setCaptureExperimentalAttributes(boolean captureExperimentalAttribut
this.captureExperimentalAttributes = captureExperimentalAttributes;
}

/**
* Sets whether the code attributes (file name, class name, method name and line number) should be
* set to logs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://logback.qos.ch/manual/layouts.html states Generating the line number information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue. (same for other code attributes). Should we also mention this here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I have added a sentence about this.

@trask
Copy link
Member

trask commented Sep 12, 2022

I'm looking into the CI failure, I suspect that is my doing...

@trask
Copy link
Member

trask commented Sep 12, 2022

I merged in main to fix CI

@trask trask added this to the v1.18.0 milestone Sep 13, 2022
StackTraceElement[] callerData = loggingEvent.getCallerData();
if (callerData != null && callerData.length > 0) {
StackTraceElement firstStackElement = callerData[0];
attributes.put(SemanticAttributes.CODE_FILEPATH, firstStackElement.getFileName());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StackTraceElement#getFileName() might return null, let's null-check it before passing it to attributes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I did not know that null attributes have not to bet set

attributes.put(SemanticAttributes.CODE_FILEPATH, firstStackElement.getFileName());
attributes.put(SemanticAttributes.CODE_NAMESPACE, firstStackElement.getClassName());
attributes.put(SemanticAttributes.CODE_FUNCTION, firstStackElement.getMethodName());
attributes.put(SemanticAttributes.CODE_LINENO, firstStackElement.getLineNumber());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StackTraceElement#getLineNumber() might return -1 -- in which case we probably don't want to add the attribute at all, since it represents an absent value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

assertThat(log.getAttributes().get(SemanticAttributes.EXCEPTION_TYPE)).isEqualTo(IllegalStateException.getName())
assertThat(log.getAttributes().get(SemanticAttributes.EXCEPTION_MESSAGE)).isEqualTo("hello")
assertThat(log.getAttributes().get(SemanticAttributes.EXCEPTION_STACKTRACE)).contains(LogbackTest.name)
} else {
assertThat(log.getAttributes().size()).isEqualTo(2)
assertThat(log.getAttributes().size()).isEqualTo(2 + 4) // 4 code attributes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add code attributes assertions to the javaagent test too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the nature of the Groovy test, the attribute values are not very readable:

file = NativeMethodAccessorImpl.java
codeClass = jdk.internal.reflect.NativeMethodAccessorImpl
method = invoke0

The attribute values are checked in a library test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, forgot that was groovy. Nevermind then 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya, it would be nice to have validation that the attributes are working inside of the Java agent as well, but can get to that later, I've opened #6604 to track

@@ -115,13 +114,27 @@ void logWithExtras() {
.isLessThan(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli()));
assertThat(logData.getSeverity()).isEqualTo(Severity.INFO);
assertThat(logData.getSeverityText()).isEqualTo("INFO");
assertThat(logData.getAttributes().size()).isEqualTo(3);
assertThat(logData.getAttributes().size()).isEqualTo(3 + 4); // 4 code attributes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT about refactoring this to use OpenTelemetryAssertions and AttributesAssert? Would be way more terse than the current code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not aware about these classes. Thanks! I have a first look at the OpenTelemetryAssertions and AttributesAssert classes. From what I have seen, I have not the feeling that the assertions would be shorter and easier to read (for example the assertAttributes method of AttributesAssert requires a Map). Maybe I could look at this thing more in depth and propose potential improvements in another PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that sounds fine 👍

@@ -44,6 +44,13 @@ class LogbackTest extends AgentInstrumentationSpecification {
waitForTraces(1)
}

String jvmVersion = System.getProperty("java.vm.specification.version")
int codeAttributes = 3
boolean jvmVersionGreaterThanOrEqualTo18 = jvmVersion.startsWith("1.8") && Integer.parseInt(jvmVersion) >= 18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't this throw NumberFormatException for 1.8?

if you need to test locally with different Java versions, check out https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/contributing/running-tests.md#executing-tests-with-specific-java-version

int codeAttributes = 3
boolean jvmVersionGreaterThanOrEqualTo18 = jvmVersion.startsWith("1.8") && Integer.parseInt(jvmVersion) >= 18
if (jvmVersionGreaterThanOrEqualTo18) {
codeAttributes = 4 // Java 18 specificity on line number
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a bit more detail to this comment, I'm not familiar with why Java 18 would have different behavior here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a thing

@trask
Copy link
Member

trask commented Sep 13, 2022

@jeanbisutti heads up I merged main into your branch to get CI fix for markdown link

@@ -44,6 +44,13 @@ class LogbackTest extends AgentInstrumentationSpecification {
waitForTraces(1)
}

String jvmVersion = System.getProperty("java.vm.specification.version")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use this instead? (this is the property we check for java version in the agent)

Suggested change
String jvmVersion = System.getProperty("java.vm.specification.version")
String jvmVersion = System.getProperty("java.version")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. System.getProperty("java.version") contains the minor JVM version and the number parsing just after will fail

int codeAttributes = 3
boolean jvmVersionGreaterThanOrEqualTo18 = !jvmVersion.startsWith("1.8") && Integer.parseInt(jvmVersion) >= 18
if (jvmVersionGreaterThanOrEqualTo18) {
codeAttributes = 4 // Java 18 specificity on line number (lineNumber > 0 check)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is because of groovy, I would be surprised to see different behavior for a regular Java class, I may try to convert this test to Java after merging it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line number is negative for Java <= 17 and this Groovy test, everything is fine for the library test based on JUnit 5

@trask trask merged commit f135169 into open-telemetry:main Sep 13, 2022
LironKS pushed a commit to helios/opentelemetry-java-instrumentation that referenced this pull request Oct 23, 2022
* Add code attributes for Logback

* Rename property

* Add a note about performance

* Add null check on file name

* Add check on line number

* Fix test following new behavior

* spotless

* Update instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java

Co-authored-by: Mateusz Rzeszutek <[email protected]>

* Fix test

* Adapt test for Java 18

* codenarc

* Test fix

Co-authored-by: Trask Stalnaker <[email protected]>
Co-authored-by: Mateusz Rzeszutek <[email protected]>
LironKS pushed a commit to helios/opentelemetry-java-instrumentation that referenced this pull request Oct 31, 2022
* Add code attributes for Logback

* Rename property

* Add a note about performance

* Add null check on file name

* Add check on line number

* Fix test following new behavior

* spotless

* Update instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java

Co-authored-by: Mateusz Rzeszutek <[email protected]>

* Fix test

* Adapt test for Java 18

* codenarc

* Test fix

Co-authored-by: Trask Stalnaker <[email protected]>
Co-authored-by: Mateusz Rzeszutek <[email protected]>
LironKS pushed a commit to helios/opentelemetry-java-instrumentation that referenced this pull request Dec 4, 2022
* Add code attributes for Logback

* Rename property

* Add a note about performance

* Add null check on file name

* Add check on line number

* Fix test following new behavior

* spotless

* Update instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java

Co-authored-by: Mateusz Rzeszutek <[email protected]>

* Fix test

* Adapt test for Java 18

* codenarc

* Test fix

Co-authored-by: Trask Stalnaker <[email protected]>
Co-authored-by: Mateusz Rzeszutek <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants